﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using AppEnvironment.Lib;
using AppEnvironment.Web;
using System.Collections;
using DPM.Dto;

namespace AppEnvironment.Web
{
    public static class AssigningExtensions
    {
        public static void Assign(this PlaceHolder placeHolder, bool visible)
        {
            placeHolder.Visible = visible;
        }

        public static void Assign(this ITextControl control, string value)
        {
            if (control != null)
            {
                control.Text = value;
            }
        }

        public static void Assign(this ITextControl control, int value)
        {
            if (control != null)
            {
                control.Text = value.ToString();
            }
        }

        public static void Assign(this HiddenField control, string value)
        {
            if (control != null)
            {
                control.Value = value;
            }
        }

        public static void Assign(this HiddenField control, int value)
        {
            control.Assign(value.ToString());
        }

        public static string Read(this HiddenField self)
        {
            if (self == null)
            {
                return "";
            }
            else
            {
                return self.Value;
            }
        }

        public static void Assign(this HyperLink control, string value)
        {
            if (control != null)
            {
                control.NavigateUrl = value;
            }
        }

        public static Control Assign(this Control control, bool value)
        {
            var checkbox = control as ICheckBoxControl;
            if (checkbox != null)
            {
                checkbox.Checked = value;
            }
            else if (control != null)
            {
                control.Visible = value;
            }
            
            return control;
        }

        public static bool Read(this ICheckBoxControl self)
        {
            if (self == null)
            {
                return false;
            }
            else
            {
                return self.Checked;
            }
        }

        public static string Read(this ITextControl self)
        {
            if (self == null)
            {
                return "";
            }
            else
            {
                return self.Text;
            }
        }


        public static void Assign(this Image control, string value)
        {
            if (control != null)
            {
                control.ImageUrl = value;
            }
        }

        public static void Assign(this IButtonControl control, Action action)
        {
            if (control != null)
            {
                control.Click += (sender, args) => { action(); };
            }
        }

        public static void Assign<T>(this Repeater repeater, IEnumerable<T> values, Action<RepeaterItem, T> action)
        {
            if ((repeater != null) && (values != null) && (action != null))
            {
                RepeaterBinder<T> binder = new RepeaterBinder<T>();
                binder.Bind(repeater, values, (sender, e) =>
                {
                    action(e.Item, binder.Data);
                });
            }
        }

        public static IEnumerable<RepeaterItem> Read(this Repeater self)
        {
            return
                from RepeaterItem item in self.Items
                select item;
        }

        public static T Read<T>(this Control container, string controlName)
        {
            return (T)(object)container.FindControl(controlName);
        }

        public static ListControl Assign<T>(this Control container, string controlName, IEnumerable<IdNameDto> list)
            where T : ListControl
        {
            return container.Read<T>(controlName).Assign(list);            
        }

        public static T Assign<T>(this Control container, string controlName, int value)
            where T : Control
        {
            return container.Assign<T>(controlName, value.ToString());
        }

        public static T Assign<T>(this Control container, string controlName, string value)
            where T : Control
        {
            T control = container.FindControl(controlName) as T;
            if (control != null)
            {

                ITextControl textControl = control as ITextControl;
                if (textControl != null)
                {
                    textControl.Assign(value);
                }
                else
                {
                    Image image = control as Image;
                    if (image != null)
                    {
                        image.Assign(value);
                    }
                    else
                    {
                        HyperLink hyperLink = control as HyperLink;
                        if (hyperLink != null)
                        {
                            hyperLink.Assign(value);
                        }
                        else
                        {
                            HiddenField hidden = control as HiddenField;
                            if (hidden != null)
                            {
                                hidden.Assign(value);
                            }
                            else
                            {
                                throw new Exception("Unknown type of control");
                            }
                        }
                    }
                }
            }
            return control;
        }

        public static T Assign<T>(this Control container, string controlName, bool value)
            where T : Control
        {
            T control = container.FindControl(controlName) as T;
            if (control != null)
            {
                control.Assign(value);
            }
            return control;
        }

        public static Repeater Assign<T>(this Control container, string controlName, IEnumerable<T> value, Action<RepeaterItem, T> action)
        {
            var control = container.FindControl(controlName);

            var repeater = control as Repeater;
            if (repeater != null)
            {
                repeater.Assign<T>(value, action);
            }
            else
            {
                throw new Exception("Unknown type of control");
            }

            return repeater;
        }

        public static ListControl Assign(this ListControl control, IEnumerable<IdNameDto> list)
        {
            BindListSimple(control, list);
            return control;
        }

       

        public static ListControl Assign(this ListControl control, IEnumerable<IdNameDto> list, string selectedValue)
        {
            BindListSimple(control, list, selectedValue);
            return control;
        }

        public static ListControl Assign(this ListControl control, IEnumerable<IdNameDto> list, int selectedValue)
        {
            BindListSimple(control, list, selectedValue);
            return control;
        }

        public static ListControl Assign(this ListControl control, IEnumerable<IdNameDto> list, int? selectedValue)
        {
            if (selectedValue.HasValue)
            {
                BindListSimple(control, list, selectedValue.Value);
            }
            else
            {
                control.Assign(list);
            }
            return control;
        }

        public static ListControl Assign(this ListControl control, IEnumerable<IdNameDto> list, IEnumerable<int> selectedValues)
        {
            BindListSimple(control, list, selectedValues.Select(selectedValue => selectedValue.ToString()));
            return control;
        }

        static void BindListSimple(ListControl listControl, IEnumerable list)
        {
            BindListSimple(listControl, list, "Id", "Name", new string[] { });
        }

        static void BindListSimple(ListControl listControl, IEnumerable list, string selectedValue)
        {
            BindListSimple(listControl, list, "Id", "Name", selectedValue);
        }

        static void BindListSimple(ListControl listControl, IEnumerable list, int selectedValue)
        {
            BindListSimple(listControl, list, "Id", "Name", selectedValue.ToString());
        }

        static void BindListSimple(ListControl listControl, IEnumerable list, IEnumerable<string> selectedValues)
        {
            BindListSimple(listControl, list, "Id", "Name", selectedValues);
        }

        static void BindListSimple(ListControl listControl, IEnumerable list, string displayName, string selectedValue)
        {
            BindListSimple(listControl, list, "Id", displayName, selectedValue);
        }

        static void BindListSimple(ListControl listControl, IEnumerable list, string idName, string displayName, string selectedValue)
        {
            BindListSimple(listControl, list, idName, displayName, new string[] { selectedValue });
        }

        static void BindListSimple(ListControl listControl, IEnumerable list, string idName, string displayName, IEnumerable<string> selectedValues)
        {
            if (listControl.AppendDataBoundItems)
            {
                int predefItems = listControl.Attributes["PredefItems"].As<int>(-1);
                if (predefItems == -1)
                {
                    predefItems = listControl.Items.Count;
                    listControl.Attributes["PredefItems"] = predefItems.ToString(); //first-time bound
                }
                else
                {
                    if ((predefItems > 0) && (listControl.Items.Count > predefItems))
                    {
                        //been bound already, clear all except predefined items
                        for (int index = listControl.Items.Count - 1; index > predefItems - 1; index--)
                        {
                            listControl.Items.RemoveAt(index);
                        }
                    }
                }
            }

            listControl.DataSource = list;
            listControl.DataValueField = idName;
            listControl.DataTextField = displayName;
            listControl.DataBind();

            //set selection
            foreach (string selectedValue in selectedValues)
            {
                for (int i = 0; i < listControl.Items.Count; i++)
                {
                    if (listControl.Items[i].Value == selectedValue)
                    {
                        listControl.Items[i].Selected = true;
                        break;
                    }
                }
            }
        }

        public static IEnumerable<string> Read(this ListControl self, ListControlReturnType returnType)
        {
            switch (returnType)
            {
                case ListControlReturnType.SelectedValue:
                    yield return self.SelectedValue;
                    break;
                case ListControlReturnType.SelectedItems:
                    foreach (ListItem item in self.Items)
                    {
                        if (item.Selected)
                        {
                            yield return item.Value;
                        }
                    }
                    break;
            }
            
        }
    }

    public enum ListControlReturnType
    {
        SelectedValue,
        SelectedItems
    }
}
